package cn.tramy.pinxian.wind.interceptor

import cn.tramy.pinxian.common.util.logger
import cn.tramy.pinxian.wind.domain.DomainModelHolder
import cn.tramy.pinxian.wind.event.EventBus
import cn.tramy.pinxian.wind.handler.DomainMessageWrap
import cn.tramy.pinxian.wind.handler.dispatch.DispatchTaskHolder
import org.springframework.transaction.support.TransactionSynchronization
import reactor.core.publisher.toFlux


class DomainTransactionSynchronization(private val eventBus: EventBus) : TransactionSynchronization {

    companion object {
        private val LOGGER = logger(DomainTransactionSynchronization::class.java)
    }

    override fun afterCommit() {
        super.afterCommit()
        LOGGER.debug("Transaction is committed.After commit.")
        DispatchTaskHolder.current().tasks().toFlux().doFinally { DispatchTaskHolder.current().reset() }.subscribe { it.run() }
    }

    override fun beforeCommit(readOnly: Boolean) {
        super.beforeCommit(readOnly)
        LOGGER.debug("Transaction is not committed. Before commit. readOnly=$readOnly")

        if (!readOnly) {
            DomainModelHolder.current().domainModels().toFlux().doFinally { DomainModelHolder.current().reset() }
                    .subscribe {
                        it.domainEvents().forEach { event ->
                            val msgWrap = DomainMessageWrap(event, it.uid, it::class.java)
                            this.eventBus.send(msgWrap)
                        }
                    }
        }
    }
}